//
// Created by youle on 20-1-14.
//
#include <vector>
#include <arpa/inet.h>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <string>
#include "utils.h"
#include "string.h"

#include "utils/jf_log.h"
#include "utils/ghc/filesystem.hpp"
namespace fs = ghc::filesystem;

using namespace std;

//P为线外一点，AB为线段两个端点
float GetDist_P2L(const VertPoint& pointP, const VertPoint& pointA, const VertPoint& pointB) {
    //求直线方程
    int A = 0, B = 0, C = 0;
    A = pointA.y - pointB.y;
    B = pointB.x - pointA.x;
    C = pointA.x*pointB.y - pointA.y*pointB.x;
    //代入点到直线距离公式
    float distance = 0;
    distance = ((float)abs(A*pointP.x + B*pointP.y + C)) / ((float)sqrtf(A*A + B*B));
    return distance;
}

//P为线外一点，AB为线段两个端点, 获得点x轴 跟线焦点的x坐标
int GetX_P2L(const VertPoint& pointP, const VertPoint& pointA, const VertPoint& pointB){
    static const float EP = 0.000001;
    float xlen = pointA.x - pointB.x;
    if(xlen <= EP){
        return pointA.x;
    }
    float ylen = pointA.y - pointB.y;

    float pylen = pointP.y - pointB.y;

    float factor = ylen/xlen;
    float dx = pylen/factor;
    float relx = pointA.x - dx;
    return int(relx);
}

bool PointInPnpoly(const std::vector<VertPoint> & verts, const VertPoint & point) {
// 这个测试都过不了。。。直接返回false；
    int nvert = verts.size();

    float minX = verts[0].x;
    float minY = verts[0].y;
    float maxX = verts[0].x;
    float maxY = verts[0].y;
    for(int i=1; i < nvert; i++){
        // x
        if(minX > verts[i].x){
            minX = verts[i].x;
        }
        if(maxX < verts[i].x){
            maxX = verts[i].x;
        }

        // y
        if(minY > verts[i].y){
            minY = verts[i].y;
        }
        if(maxY < verts[i].y){
            maxY = verts[i].y;
        }
    }

    if (point.x < minX || point.x > maxX || point.y < minY || point.y > maxY) {
        return false;
    }
    //是核心算法部分：
    int c = false;
    for (int i = 0, j = nvert - 1; i < nvert; j = i++){
        if (((verts[i].y > point.y) != (verts[j].y > point.y)) &&
            (point.x < (verts[j].x - verts[i].x) * (point.y - verts[i].y) / (verts[j].y - verts[i].y) + verts[i].x)){
            c = !c;
        }
    }
    return c;
}



const string GetStrCurrentSystemTime()
{
    auto tt = std::chrono::system_clock::to_time_t
            (std::chrono::system_clock::now());
    struct tm* ptm = localtime(&tt);
    char date[60] = {0};
    sprintf(date, "%d%02d%02d-%02d%02d%02d",
            ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
            ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    return std::string(date);
}

int IsFileExist(const char* file_path){
    if(file_path == nullptr){
        return -1;
    }
    if(access(file_path, F_OK) != 0){
        return -2;
    }
    return 0;
}

int IsDirExist(const char* dir_path){
    if(dir_path == nullptr){
        return -1;
    }
    if(opendir(dir_path) == nullptr){
        return -2;
    }
    return 0;
}

int CreateDir(const char *sPathName){
    char dirName[256] = {0};
    strcpy(dirName, sPathName);
    int len = (int)strlen(dirName);
    if(dirName[len - 1] != '/') {
        strcat(dirName, "/");
    }
    len = (int)strlen(dirName);
    for(int i=1; i<len; i++){
        if(dirName[i] == '/'){
            dirName[i] = 0;
            if(access(dirName, 0) != 0){
                if(mkdir(dirName, 0755) == -1){
                    perror("mkdir error");
                    return -1;
                }
            }
            dirName[i] = '/';
        }
    }
    return   0;
}

int JudgeSystem() {
    typedef union _Un {
        char c[4];
        int i;
    } Un;

    Un un;
    un.i = 1;

    //如果是小端则返回1，如果是大端则返回0
    return un.c[0];
}

uint64_t Host2Net(const uint64_t & i64_host){
    uint64_t i64_net = 0;
    uint32_t i32_host_h = 0;
    uint32_t i32_host_l = 0;

    i32_host_l = i64_host & 0xffffffff;
    i32_host_h = (i64_host >> 32) & 0xffffffff;

    i64_net = htonl(i32_host_l);
    i64_net = ( i64_net << 32 ) | htonl(i32_host_h);
    return i64_net;
}

const string & GetRootDir(){
    static string rootDir;
    if(rootDir.empty()){
        char curDir[512] = {0};
        getcwd(curDir, 500);
        fs::path rootPath(curDir);
        rootDir = rootPath.parent_path();
    }
    return rootDir;
}
